﻿using KinectLibrary;
using KinectLibrary.DTWGestureRecognition;
using Microsoft.Kinect;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace SLA
{
    public enum DrawingType
    {
        NONE, SMALL, BIG
    };
    public static class DrawingHelper
    {
        public static Point TransformPoint(Canvas cnv, int x, int y)
        {
            return new Point((int)(cnv.ActualWidth * x / 640), (int)(cnv.ActualHeight * y / 480));
        }

        public static void DrawFrame(KinectLibrary.Frame frame, Canvas canvasFrame, DrawingType type)
        {
            var bodySegment1 = GetBodySegment(canvasFrame, frame.Joints, JointType.HipCenter, JointType.Spine, JointType.ShoulderCenter, JointType.Head);
            var bodySegment2 = GetBodySegment(canvasFrame, frame.Joints, JointType.ShoulderCenter, JointType.ShoulderLeft, JointType.ElbowLeft, JointType.WristLeft, JointType.HandLeft);
            var bodySegment3 = GetBodySegment(canvasFrame, frame.Joints, JointType.ShoulderCenter, JointType.ShoulderRight, JointType.ElbowRight, JointType.WristRight, JointType.HandRight);

            canvasFrame.Children.Clear();
            DrawPolygon(canvasFrame, bodySegment1, type);
            DrawPolygon(canvasFrame, bodySegment2, type);
            DrawPolygon(canvasFrame, bodySegment3, type);
            foreach (var joint in frame.Joints)
            {
                var point = DrawingHelper.TransformPoint(canvasFrame, (int)joint.Position.X, (int)joint.Position.Y);
                canvasFrame.Children.Add(new Ellipse
                {
                    Fill = Brushes.Blue,
                    Width = 5,
                    Height = 5,
                    Margin = new Thickness(point.X - 2.5, point.Y - 2.5, 0, 0)
                });
            }

            var rightHandJoint = frame.Joints.FirstOrDefault(j => j.JointType == JointType.HandRight);
            var rightHand = DrawingHelper.TransformPoint(canvasFrame, (int)rightHandJoint.Position.X, (int)rightHandJoint.Position.Y);
            var leftHandJoint = frame.Joints.FirstOrDefault(j => j.JointType == JointType.HandLeft);
            var leftHand = DrawingHelper.TransformPoint(canvasFrame, (int)leftHandJoint.Position.X, (int)leftHandJoint.Position.Y);

            foreach (var hand in frame.Hands)
            {
                foreach (var finger in hand.Fingers)
                {
                    if (finger.Position.X != Hand.FingerNotFound.X)
                    {
                        var point = DrawingHelper.TransformPoint(canvasFrame, (int)finger.Position.X, (int)finger.Position.Y);
                        var distRight = double.PositiveInfinity;
                        var distLeft = double.PositiveInfinity;

                        if (rightHand != null)
                        {
                            distRight = MathHelper.GetDistance(point.X, rightHand.X, point.Y, rightHand.Y);
                        }
                        if (leftHand != null)
                        {
                            distLeft = MathHelper.GetDistance(point.X, leftHand.X, point.Y, leftHand.Y);
                        }

                        if (distRight < distLeft)
                        {
                            if (rightHand != null)
                            {
                                canvasFrame.Children.Add(new Line
                                {
                                    Stroke = Brushes.BlueViolet,
                                    StrokeThickness = 1,
                                    X1 = point.X,
                                    Y1 = point.Y,
                                    X2 = rightHand.X,
                                    Y2 = rightHand.Y
                                });
                            }
                        }
                        else if (distRight > distLeft)
                        {
                            if (leftHand != null)
                            {
                                canvasFrame.Children.Add(new Line
                                {
                                    Stroke = Brushes.BlueViolet,
                                    StrokeThickness = 1,
                                    X1 = point.X,
                                    Y1 = point.Y,
                                    X2 = leftHand.X,
                                    Y2 = leftHand.Y
                                });
                            }
                        }

                        canvasFrame.Children.Add(new Ellipse
                        {
                            Fill = Brushes.DarkBlue,
                            Width = 3,
                            Height = 3,
                            Margin = new Thickness(point.X - 1.5, point.Y - 1.5, 0, 0)
                        });
                    }
                }
            }
        }

        public static void DrawPolygon(Canvas canvas, Point[] points, DrawingType type)
        {
            var brush = Brushes.Black;
            var stroke = 1;
            if (type == DrawingType.SMALL)
            {
                brush = Brushes.DarkBlue;
                stroke = 2;
            }
            else if (type == DrawingType.BIG)
            {
                brush = Brushes.Green;
                stroke = 5;
            }
            if (points.Length > 1)
            {
                for (int i = 0; i < points.Length - 1; i++)
                {
                    canvas.Children.Add(new Line()
                    {
                        Stroke = brush,
                        StrokeThickness = stroke,
                        X1 = points[i].X,
                        Y1 = points[i].Y,
                        X2 = points[i + 1].X,
                        Y2 = points[i + 1].Y
                    });
                }
            }
        }

        public static Point[] GetBodySegment(Canvas canvasFrame, IEnumerable<Articulation> joints, params JointType[] ids)
        {
            var points = new Point[ids.Count()];

            int iJoint = 0;
            foreach (JointType t in ids)
            {
                var joint = joints.FirstOrDefault(j => j.JointType == t);
                if (joint != null)
                {
                    points[iJoint] = DrawingHelper.TransformPoint(canvasFrame, (int)joint.Position.X, (int)joint.Position.Y);
                    iJoint++;
                }
            }

            return points;
        }
    }
}
